---
title: "Control Flow - Conditionals, Loops, and Pattern Matching"
description: "Learn Swift control flow: conditionals, loops, switch statements, and pattern matching with JavaScript comparisons"
---

# Control Flow: Conditionals, Loops, and Pattern Matching

In this module, we'll explore Swift's control flow structures and compare them with JavaScript's conditional statements and loops. Swift provides powerful control flow features including enhanced switch statements with pattern matching, which are more expressive than JavaScript's switch statements.

## Table of Contents

- [Conditional Statements](#conditional-statements)
- [Loops](#loops)
- [Switch Statements](#switch-statements)
- [Pattern Matching](#pattern-matching)
- [Control Transfer Statements](#control-transfer-statements)
- [Error Handling Basics](#error-handling-basics)
- [Exercises](#exercises)
- [Key Takeaways](#key-takeaways)

## Conditional Statements

Swift's conditional statements are similar to JavaScript's but with some key differences in syntax and behavior.

### If Statements

<UniversalEditor title="If Statements Comparison" compare={true}>
```javascript !! js
// JavaScript if statements
let age = 25;
let hasLicense = true;

// Basic if statement
if (age >= 18) {
    console.log("You are an adult");
}

// If-else statement
if (age >= 18) {
    console.log("You can vote");
} else {
    console.log("You cannot vote yet");
}

// If-else if-else chain
if (age < 13) {
    console.log("Child");
} else if (age < 20) {
    console.log("Teenager");
} else if (age < 65) {
    console.log("Adult");
} else {
    console.log("Senior");
}

// Conditional with logical operators
if (age >= 18 && hasLicense) {
    console.log("You can drive");
} else {
    console.log("You cannot drive");
}

// Ternary operator
let status = age >= 18 ? "adult" : "minor";
```

```swift !! swift
// Swift if statements
let age = 25
let hasLicense = true

// Basic if statement
if age >= 18 {
    print("You are an adult")
}

// If-else statement
if age >= 18 {
    print("You can vote")
} else {
    print("You cannot vote yet")
}

// If-else if-else chain
if age < 13 {
    print("Child")
} else if age < 20 {
    print("Teenager")
} else if age < 65 {
    print("Adult")
} else {
    print("Senior")
}

// Conditional with logical operators
if age >= 18 && hasLicense {
    print("You can drive")
} else {
    print("You cannot drive")
}

// Ternary operator
let status = age >= 18 ? "adult" : "minor"

// Swift-specific: Optional binding in if statements
let optionalName: String? = "John"
if let name = optionalName {
    print("Hello, \(name)")
} else {
    print("No name provided")
}

// Multiple optional bindings
let optionalAge: Int? = 25
let optionalCity: String? = "New York"
if let age = optionalAge, let city = optionalCity {
    print("\(age) years old from \(city)")
}
```
</UniversalEditor>

### Guard Statements

Swift's guard statement is a powerful control flow feature that doesn't exist in JavaScript.

<UniversalEditor title="Guard Statements" compare={true}>
```javascript !! js
// JavaScript: Early return pattern (equivalent to guard)
function processUser(user) {
    // Early return for validation
    if (!user) {
        return "No user provided";
    }
    
    if (!user.name) {
        return "User has no name";
    }
    
    if (!user.email) {
        return "User has no email";
    }
    
    // Main logic here
    return `Processing user: ${user.name} (${user.email})`;
}

// Usage
const user1 = { name: "John", email: "john@example.com" };
const user2 = { name: "Jane" };
console.log(processUser(user1)); // "Processing user: John (john@example.com)"
console.log(processUser(user2)); // "User has no email"
```

```swift !! swift
// Swift guard statements
func processUser(_ user: [String: Any]?) -> String {
    // Guard for early exit
    guard let user = user else {
        return "No user provided"
    }
    
    guard let name = user["name"] as? String else {
        return "User has no name"
    }
    
    guard let email = user["email"] as? String else {
        return "User has no email"
    }
    
    // Main logic here - user, name, and email are available
    return "Processing user: \(name) (\(email))"
}

// Usage
let user1: [String: Any] = ["name": "John", "email": "john@example.com"]
let user2: [String: Any] = ["name": "Jane"]
print(processUser(user1)) // "Processing user: John (john@example.com)"
print(processUser(user2)) // "User has no email"

// Guard with multiple conditions
func validateUser(_ user: [String: Any]) -> Bool {
    guard let name = user["name"] as? String,
          let age = user["age"] as? Int,
          age >= 18 else {
        return false
    }
    
    // All validations passed
    return true
}
```
</UniversalEditor>

## Loops

Swift provides several types of loops, each with specific use cases and performance characteristics.

### For Loops

<UniversalEditor title="For Loops Comparison" compare={true}>
```javascript !! js
// JavaScript for loops
let numbers = [1, 2, 3, 4, 5];

// Traditional for loop
for (let i = 0; i < numbers.length; i++) {
    console.log(numbers[i]);
}

// For...of loop (iterate over values)
for (let number of numbers) {
    console.log(number);
}

// For...in loop (iterate over indices/keys)
for (let index in numbers) {
    console.log(`Index ${index}: ${numbers[index]}`);
}

// ForEach method
numbers.forEach((number, index) => {
    console.log(`Number ${index}: ${number}`);
});

// Range-based loop
for (let i = 1; i <= 5; i++) {
    console.log(i);
}

// Iterating over object properties
let person = { name: "John", age: 30, city: "NYC" };
for (let key in person) {
    console.log(`${key}: ${person[key]}`);
}
```

```swift !! swift
// Swift for loops
let numbers = [1, 2, 3, 4, 5]

// For-in loop (iterate over values)
for number in numbers {
    print(number)
}

// For-in with indices
for (index, number) in numbers.enumerated() {
    print("Index \(index): \(number)")
}

// Range-based loop
for i in 1...5 {
    print(i)
}

// Half-open range
for i in 1..<5 {
    print(i) // Prints 1, 2, 3, 4
}

// Stride for custom ranges
for i in stride(from: 0, to: 10, by: 2) {
    print(i) // Prints 0, 2, 4, 6, 8
}

// Iterating over dictionary
let person: [String: Any] = ["name": "John", "age": 30, "city": "NYC"]
for (key, value) in person {
    print("\(key): \(value)")
}

// ForEach method (functional approach)
numbers.enumerated().forEach { index, number in
    print("Number \(index): \(number)")
}

// Swift-specific: Where clause in for loops
for number in numbers where number % 2 == 0 {
    print("Even number: \(number)")
}
```
</UniversalEditor>

### While and Repeat-While Loops

<UniversalEditor title="While Loops Comparison" compare={true}>
```javascript !! js
// JavaScript while loops
let count = 0;

// While loop
while (count < 5) {
    console.log(count);
    count++;
}

// Do-while loop (execute at least once)
let number = 0;
do {
    console.log(number);
    number++;
} while (number < 3);

// While loop with break
let i = 0;
while (true) {
    if (i >= 5) {
        break;
    }
    console.log(i);
    i++;
}

// While loop with continue
let j = 0;
while (j < 10) {
    j++;
    if (j % 2 === 0) {
        continue; // Skip even numbers
    }
    console.log(j);
}
```

```swift !! swift
// Swift while loops
var count = 0

// While loop
while count < 5 {
    print(count)
    count += 1
}

// Repeat-while loop (execute at least once)
var number = 0
repeat {
    print(number)
    number += 1
} while number < 3

// While loop with break
var i = 0
while true {
    if i >= 5 {
        break
    }
    print(i)
    i += 1
}

// While loop with continue
var j = 0
while j < 10 {
    j += 1
    if j % 2 == 0 {
        continue // Skip even numbers
    }
    print(j)
}

// Swift-specific: While loop with optional binding
var optionalNumbers: [Int?] = [1, nil, 3, nil, 5]
var index = 0
while index < optionalNumbers.count {
    if let number = optionalNumbers[index] {
        print("Found number: \(number)")
    }
    index += 1
}
```
</UniversalEditor>

## Switch Statements

Swift's switch statements are much more powerful than JavaScript's, supporting pattern matching and complex conditions.

### Basic Switch Statements

<UniversalEditor title="Basic Switch Statements" compare={true}>
```javascript !! js
// JavaScript switch statement
let day = "Monday";

switch (day) {
    case "Monday":
        console.log("Start of work week");
        break;
    case "Tuesday":
    case "Wednesday":
    case "Thursday":
        console.log("Mid week");
        break;
    case "Friday":
        console.log("TGIF!");
        break;
    case "Saturday":
    case "Sunday":
        console.log("Weekend!");
        break;
    default:
        console.log("Invalid day");
}

// Switch with fall-through (explicit)
let grade = "B";
switch (grade) {
    case "A":
        console.log("Excellent");
        // Fall through
    case "B":
        console.log("Good");
        break;
    case "C":
        console.log("Average");
        break;
    default:
        console.log("Needs improvement");
}
```

```swift !! swift
// Swift switch statement
let day = "Monday"

switch day {
case "Monday":
    print("Start of work week")
case "Tuesday", "Wednesday", "Thursday":
    print("Mid week")
case "Friday":
    print("TGIF!")
case "Saturday", "Sunday":
    print("Weekend!")
default:
    print("Invalid day")
}

// Switch with fall-through (explicit)
let grade = "B"
switch grade {
case "A":
    print("Excellent")
    fallthrough
case "B":
    print("Good")
case "C":
    print("Average")
default:
    print("Needs improvement")
}

// Swift-specific: Switch with ranges
let score = 85
switch score {
case 90...100:
    print("A")
case 80..<90:
    print("B")
case 70..<80:
    print("C")
case 60..<70:
    print("D")
case 0..<60:
    print("F")
default:
    print("Invalid score")
}

// Switch with tuples
let point = (2, 0)
switch point {
case (0, 0):
    print("Origin")
case (_, 0):
    print("On x-axis")
case (0, _):
    print("On y-axis")
case (-2...2, -2...2):
    print("Near origin")
default:
    print("Somewhere else")
}
```
</UniversalEditor>

### Advanced Switch with Pattern Matching

<UniversalEditor title="Advanced Switch with Pattern Matching" compare={true}>
```javascript !! js
// JavaScript: Complex conditional logic (no direct equivalent)
function processValue(value) {
    if (typeof value === "string") {
        if (value.length === 0) {
            return "Empty string";
        } else if (value.length < 10) {
            return "Short string";
        } else {
            return "Long string";
        }
    } else if (typeof value === "number") {
        if (value === 0) {
            return "Zero";
        } else if (value > 0) {
            return "Positive number";
        } else {
            return "Negative number";
        }
    } else if (Array.isArray(value)) {
        if (value.length === 0) {
            return "Empty array";
        } else {
            return `Array with ${value.length} items`;
        }
    } else if (value === null) {
        return "Null value";
    } else {
        return "Unknown type";
    }
}

// Usage
console.log(processValue("hello")); // "Short string"
console.log(processValue(42)); // "Positive number"
console.log(processValue([1, 2, 3])); // "Array with 3 items"
```

```swift !! swift
// Swift: Advanced switch with pattern matching
func processValue(_ value: Any) -> String {
    switch value {
    case let str as String:
        switch str {
        case "":
            return "Empty string"
        case let s where s.count < 10:
            return "Short string"
        default:
            return "Long string"
        }
    case let num as Int:
        switch num {
        case 0:
            return "Zero"
        case let n where n > 0:
            return "Positive number"
        default:
            return "Negative number"
        }
    case let arr as [Any]:
        switch arr {
        case []:
            return "Empty array"
        case let a where a.count > 0:
            return "Array with \(a.count) items"
        default:
            return "Unknown array"
        }
    case nil:
        return "Nil value"
    default:
        return "Unknown type"
    }
}

// Usage
print(processValue("hello")) // "Short string"
print(processValue(42)) // "Positive number"
print(processValue([1, 2, 3])) // "Array with 3 items"

// Switch with enum pattern matching
enum Direction {
    case north, south, east, west
}

func describeDirection(_ direction: Direction) -> String {
    switch direction {
    case .north:
        return "Going up"
    case .south:
        return "Going down"
    case .east:
        return "Going right"
    case .west:
        return "Going left"
    }
}

// Switch with associated values
enum Measurement {
    case distance(Double)
    case temperature(Double)
    case weight(Double)
}

func describeMeasurement(_ measurement: Measurement) -> String {
    switch measurement {
    case .distance(let value):
        return "Distance: \(value) meters"
    case .temperature(let value):
        return "Temperature: \(value)°C"
    case .weight(let value):
        return "Weight: \(value) kg"
    }
}
```
</UniversalEditor>

## Pattern Matching

Swift's pattern matching capabilities go far beyond what's available in JavaScript.

### Value Binding and Where Clauses

<UniversalEditor title="Value Binding and Where Clauses" compare={true}>
```javascript !! js
// JavaScript: Complex conditional logic
function analyzeNumber(num) {
    if (typeof num === "number") {
        if (num === 0) {
            return "Zero";
        } else if (num > 0 && num < 100) {
            return `Small positive number: ${num}`;
        } else if (num >= 100 && num < 1000) {
            return `Medium positive number: ${num}`;
        } else if (num >= 1000) {
            return `Large positive number: ${num}`;
        } else {
            return `Negative number: ${num}`;
        }
    }
    return "Not a number";
}

// Complex object analysis
function analyzePerson(person) {
    if (person && typeof person === "object") {
        const { name, age, city } = person;
        if (name && age && city) {
            if (age < 18) {
                return `${name} is a minor from ${city}`;
            } else if (age >= 18 && age < 65) {
                return `${name} is an adult from ${city}`;
            } else {
                return `${name} is a senior from ${city}`;
            }
        }
    }
    return "Invalid person data";
}
```

```swift !! swift
// Swift: Pattern matching with value binding
func analyzeNumber(_ num: Int) -> String {
    switch num {
    case 0:
        return "Zero"
    case let n where n > 0 && n < 100:
        return "Small positive number: \(n)"
    case let n where n >= 100 && n < 1000:
        return "Medium positive number: \(n)"
    case let n where n >= 1000:
        return "Large positive number: \(n)"
    case let n where n < 0:
        return "Negative number: \(n)"
    default:
        return "Unexpected case"
    }
}

// Complex tuple pattern matching
func analyzePerson(_ person: (name: String, age: Int, city: String)) -> String {
    switch person {
    case let (name, age, city) where age < 18:
        return "\(name) is a minor from \(city)"
    case let (name, age, city) where age >= 18 && age < 65:
        return "\(name) is an adult from \(city)"
    case let (name, age, city) where age >= 65:
        return "\(name) is a senior from \(city)"
    default:
        return "Invalid person data"
    }
}

// Pattern matching with arrays
func analyzeArray(_ array: [Int]) -> String {
    switch array {
    case []:
        return "Empty array"
    case [let first]:
        return "Single element: \(first)"
    case [let first, let second]:
        return "Two elements: \(first), \(second)"
    case let arr where arr.count > 2:
        return "Array with \(arr.count) elements"
    default:
        return "Unknown array"
    }
}

// Pattern matching with optionals
func analyzeOptional(_ value: Int?) -> String {
    switch value {
    case nil:
        return "No value"
    case let num? where num > 0:
        return "Positive number: \(num)"
    case let num? where num < 0:
        return "Negative number: \(num)"
    case 0?:
        return "Zero"
    default:
        return "Unexpected case"
    }
}
```
</UniversalEditor>

## Control Transfer Statements

Swift provides several control transfer statements for managing program flow.

### Break, Continue, and Fallthrough

<UniversalEditor title="Control Transfer Statements" compare={true}>
```javascript !! js
// JavaScript control transfer
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Break in loops
for (let i = 0; i < numbers.length; i++) {
    if (numbers[i] === 5) {
        break; // Exit loop when 5 is found
    }
    console.log(numbers[i]);
}

// Continue in loops
for (let i = 0; i < numbers.length; i++) {
    if (numbers[i] % 2 === 0) {
        continue; // Skip even numbers
    }
    console.log(numbers[i]);
}

// Break in switch (implicit)
let day = "Monday";
switch (day) {
    case "Monday":
        console.log("Start of week");
        break; // Explicit break needed
    case "Friday":
        console.log("End of week");
        break;
    default:
        console.log("Mid week");
}

// Labeled statements
outerLoop: for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 3; j++) {
        if (i === 1 && j === 1) {
            break outerLoop; // Break outer loop
        }
        console.log(`i=${i}, j=${j}`);
    }
}
```

```swift !! swift
// Swift control transfer
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// Break in loops
for number in numbers {
    if number == 5 {
        break // Exit loop when 5 is found
    }
    print(number)
}

// Continue in loops
for number in numbers {
    if number % 2 == 0 {
        continue // Skip even numbers
    }
    print(number)
}

// Break in switch (implicit, no fallthrough)
let day = "Monday"
switch day {
case "Monday":
    print("Start of week")
    // No break needed, implicit
case "Friday":
    print("End of week")
default:
    print("Mid week")
}

// Fallthrough (explicit)
let grade = "A"
switch grade {
case "A":
    print("Excellent")
    fallthrough // Explicit fallthrough
case "B":
    print("Good")
case "C":
    print("Average")
default:
    print("Needs improvement")
}

// Labeled statements
outerLoop: for i in 0..<3 {
    for j in 0..<3 {
        if i == 1 && j == 1 {
            break outerLoop // Break outer loop
        }
        print("i=\(i), j=\(j)")
    }
}

// Swift-specific: Break with value (in switch)
enum Result {
    case success(String)
    case failure(String)
}

func processResult(_ result: Result) -> String {
    switch result {
    case .success(let message):
        return "Success: \(message)"
    case .failure(let error):
        return "Error: \(error)"
    }
}
```
</UniversalEditor>

## Error Handling Basics

Swift's error handling is more structured than JavaScript's try-catch.

<UniversalEditor title="Error Handling Comparison" compare={true}>
```javascript !! js
// JavaScript error handling
function divideNumbers(a, b) {
    if (b === 0) {
        throw new Error("Division by zero");
    }
    return a / b;
}

// Try-catch
try {
    const result = divideNumbers(10, 0);
    console.log(result);
} catch (error) {
    console.log("Error:", error.message);
}

// Try-catch with finally
try {
    const result = divideNumbers(10, 2);
    console.log("Result:", result);
} catch (error) {
    console.log("Error:", error.message);
} finally {
    console.log("Cleanup completed");
}

// Custom error types
class ValidationError extends Error {
    constructor(message) {
        super(message);
        this.name = "ValidationError";
    }
}

function validateAge(age) {
    if (age < 0) {
        throw new ValidationError("Age cannot be negative");
    }
    if (age > 150) {
        throw new ValidationError("Age seems unrealistic");
    }
    return true;
}
```

```swift !! swift
// Swift error handling
enum DivisionError: Error {
    case divisionByZero
    case invalidInput
}

func divideNumbers(_ a: Double, _ b: Double) throws -> Double {
    guard b != 0 else {
        throw DivisionError.divisionByZero
    }
    return a / b
}

// Do-catch
do {
    let result = try divideNumbers(10, 0)
    print(result)
} catch DivisionError.divisionByZero {
    print("Error: Division by zero")
} catch {
    print("Error: \(error)")
}

// Try with optional binding
if let result = try? divideNumbers(10, 2) {
    print("Result: \(result)")
} else {
    print("Error occurred")
}

// Force try (crashes if error)
let result = try! divideNumbers(10, 2) // Safe here

// Custom error types
enum ValidationError: Error {
    case negativeAge
    case unrealisticAge(Int)
    case missingName
}

func validateAge(_ age: Int) throws {
    if age < 0 {
        throw ValidationError.negativeAge
    }
    if age > 150 {
        throw ValidationError.unrealisticAge(age)
    }
}

func validatePerson(name: String?, age: Int) throws {
    guard let name = name, !name.isEmpty else {
        throw ValidationError.missingName
    }
    try validateAge(age)
    print("Valid person: \(name), age \(age)")
}

// Error handling with pattern matching
do {
    try validatePerson(name: nil, age: 25)
} catch ValidationError.negativeAge {
    print("Age cannot be negative")
} catch ValidationError.unrealisticAge(let age) {
    print("Age \(age) seems unrealistic")
} catch ValidationError.missingName {
    print("Name is required")
} catch {
    print("Unknown error: \(error)")
}
```
</UniversalEditor>

## Exercises

### Exercise 1: Grade Calculator
Create a function that takes a score and returns a grade using switch statements.

<UniversalEditor title="Exercise 1 Solution" compare={true}>
```javascript !! js
// JavaScript solution
function getGrade(score) {
    switch (true) {
        case score >= 90:
            return "A";
        case score >= 80:
            return "B";
        case score >= 70:
            return "C";
        case score >= 60:
            return "D";
        case score >= 0:
            return "F";
        default:
            return "Invalid score";
    }
}

// Test
console.log(getGrade(95)); // "A"
console.log(getGrade(85)); // "B"
console.log(getGrade(75)); // "C"
console.log(getGrade(65)); // "D"
console.log(getGrade(55)); // "F"
```

```swift !! swift
// Swift solution
func getGrade(_ score: Int) -> String {
    switch score {
    case 90...100:
        return "A"
    case 80..<90:
        return "B"
    case 70..<80:
        return "C"
    case 60..<70:
        return "D"
    case 0..<60:
        return "F"
    default:
        return "Invalid score"
    }
}

// Test
print(getGrade(95)) // "A"
print(getGrade(85)) // "B"
print(getGrade(75)) // "C"
print(getGrade(65)) // "D"
print(getGrade(55)) // "F"
```
</UniversalEditor>

### Exercise 2: Number Analyzer
Create a function that analyzes a number and returns a description using pattern matching.

<UniversalEditor title="Exercise 2 Solution" compare={true}>
```javascript !! js
// JavaScript solution
function analyzeNumber(num) {
    if (typeof num !== "number") {
        return "Not a number";
    }
    
    if (num === 0) {
        return "Zero";
    } else if (num > 0) {
        if (num % 2 === 0) {
            return "Positive even number";
        } else {
            return "Positive odd number";
        }
    } else {
        if (num % 2 === 0) {
            return "Negative even number";
        } else {
            return "Negative odd number";
        }
    }
}

// Test
console.log(analyzeNumber(0)); // "Zero"
console.log(analyzeNumber(4)); // "Positive even number"
console.log(analyzeNumber(7)); // "Positive odd number"
console.log(analyzeNumber(-2)); // "Negative even number"
console.log(analyzeNumber(-3)); // "Negative odd number"
```

```swift !! swift
// Swift solution
func analyzeNumber(_ num: Int) -> String {
    switch num {
    case 0:
        return "Zero"
    case let n where n > 0 && n % 2 == 0:
        return "Positive even number"
    case let n where n > 0 && n % 2 != 0:
        return "Positive odd number"
    case let n where n < 0 && n % 2 == 0:
        return "Negative even number"
    case let n where n < 0 && n % 2 != 0:
        return "Negative odd number"
    default:
        return "Unexpected case"
    }
}

// Test
print(analyzeNumber(0)) // "Zero"
print(analyzeNumber(4)) // "Positive even number"
print(analyzeNumber(7)) // "Positive odd number"
print(analyzeNumber(-2)) // "Negative even number"
print(analyzeNumber(-3)) // "Negative odd number"
```
</UniversalEditor>

### Exercise 3: Array Processor
Create a function that processes arrays using different control flow patterns.

<UniversalEditor title="Exercise 3 Solution" compare={true}>
```javascript !! js
// JavaScript solution
function processArray(arr) {
    if (!Array.isArray(arr)) {
        return "Not an array";
    }
    
    if (arr.length === 0) {
        return "Empty array";
    }
    
    let sum = 0;
    let hasNegative = false;
    let hasPositive = false;
    
    for (let num of arr) {
        if (typeof num !== "number") {
            continue; // Skip non-numbers
        }
        
        sum += num;
        
        if (num < 0) {
            hasNegative = true;
        } else if (num > 0) {
            hasPositive = true;
        }
    }
    
    if (hasNegative && hasPositive) {
        return "Mixed array, sum: " + sum;
    } else if (hasPositive) {
        return "All positive, sum: " + sum;
    } else if (hasNegative) {
        return "All negative, sum: " + sum;
    } else {
        return "All zeros, sum: " + sum;
    }
}

// Test
console.log(processArray([1, 2, 3])); // "All positive, sum: 6"
console.log(processArray([-1, -2, -3])); // "All negative, sum: -6"
console.log(processArray([1, -2, 3])); // "Mixed array, sum: 2"
console.log(processArray([0, 0, 0])); // "All zeros, sum: 0"
```

```swift !! swift
// Swift solution
func processArray(_ arr: [Any]) -> String {
    switch arr {
    case []:
        return "Empty array"
    case let array where array.allSatisfy({ $0 is Int }):
        let numbers = array.compactMap { $0 as? Int }
        let sum = numbers.reduce(0, +)
        
        let hasNegative = numbers.contains { $0 < 0 }
        let hasPositive = numbers.contains { $0 > 0 }
        
        switch (hasNegative, hasPositive) {
        case (true, true):
            return "Mixed array, sum: \(sum)"
        case (false, true):
            return "All positive, sum: \(sum)"
        case (true, false):
            return "All negative, sum: \(sum)"
        case (false, false):
            return "All zeros, sum: \(sum)"
        }
    default:
        return "Not a number array"
    }
}

// Alternative approach with guard
func processArrayWithGuard(_ arr: [Any]) -> String {
    guard !arr.isEmpty else {
        return "Empty array"
    }
    
    var sum = 0
    var hasNegative = false
    var hasPositive = false
    
    for element in arr {
        guard let num = element as? Int else {
            continue // Skip non-numbers
        }
        
        sum += num
        
        if num < 0 {
            hasNegative = true
        } else if num > 0 {
            hasPositive = true
        }
    }
    
    if hasNegative && hasPositive {
        return "Mixed array, sum: \(sum)"
    } else if hasPositive {
        return "All positive, sum: \(sum)"
    } else if hasNegative {
        return "All negative, sum: \(sum)"
    } else {
        return "All zeros, sum: \(sum)"
    }
}

// Test
print(processArray([1, 2, 3])) // "All positive, sum: 6"
print(processArray([-1, -2, -3])) // "All negative, sum: -6"
print(processArray([1, -2, 3])) // "Mixed array, sum: 2"
print(processArray([0, 0, 0])) // "All zeros, sum: 0"
```
</UniversalEditor>

## Key Takeaways

### Swift Control Flow Advantages
1. **Pattern Matching**: Powerful switch statements with complex pattern matching
2. **Guard Statements**: Early exit pattern for cleaner code
3. **Value Binding**: Extract values directly in switch cases
4. **Where Clauses**: Additional conditions in pattern matching
5. **Exhaustive Matching**: Compiler ensures all cases are handled

### Key Differences from JavaScript
1. **Switch Statements**: Much more powerful with pattern matching
2. **Guard Statements**: No equivalent in JavaScript
3. **Fallthrough**: Explicit vs implicit in switch statements
4. **Error Handling**: Structured try-catch with do-catch blocks
5. **Pattern Matching**: Advanced matching capabilities not available in JavaScript

### Best Practices
1. **Use guard statements** for early validation and exit
2. **Leverage pattern matching** in switch statements
3. **Prefer switch over if-else chains** for multiple conditions
4. **Use where clauses** for additional filtering
5. **Handle all cases** in switch statements
6. **Use structured error handling** with do-catch blocks

### Next Steps
In the next module, we'll explore classes and structures in Swift, including object-oriented programming concepts, inheritance, and the differences between value types and reference types. This will build upon our understanding of control flow and show how to organize code into reusable components. 